<template>
    <view style="position: relative">
        <view class="toucharea" style="" @touchstart="onTouchStart" @touchmove="onTouchMove" @touchcancel="onTouchEnd"
            @touchend="onTouchEnd">
            <view style="border-radius: 50%" :style="{
          width: props.touchRadius * 2 + 'px',
          height: props.touchRadius * 2 + 'px',
        }"></view>
        </view>
        <view class="ball" :style="{ left: uiOptions.left + 'px', top: uiOptions.top + 'px' }"
            :class="{ animation: uiOptions.inDraging === false && props.transition }">
            <slot name="ball">
                <view style="width: 60px; height: 60px; border-radius: 50%"></view>
            </slot>
        </view>
        <view class="stick" :class="{ animation: uiOptions.inDraging === false && props.transition }"
            :style="{ height: uiOptions.stickHeight + 'px', transform: 'translateX(-50%)' }">
            <view :style="{
          transform: 'rotate(' + (uiOptions.angle / (3.14159 / 180) - 90) + 'deg)',
        }" style="transform-origin: 50% 0%; width: 100%; height: 100%">
                <slot name="stick"> </slot>
            </view>
        </view>
        <view class="bottom">
            <slot name="bottom"> </slot>
        </view>
    </view>
</template>

<script setup lang="ts">
import { onMounted, reactive } from 'vue';


interface JoyStackProps {
  touchRadius: number;
  ballMoveRadius: number;
  transition: boolean;
}
const props = defineProps<JoyStackProps>();
const emit = defineEmits(['onJoyStickCancel','onJoyStickUpdate'])
const uiOptions = reactive({
  left: 0,
  top: 0,
  stickHeight: 0,
  angle: 0,
  inDraging: false,

  startLeft:0,
  startTop:0,
});

onMounted(() => {
  loop();
});


const getDistance =  (x1, y1, x2, y2) => {
  var _x = Math.abs(x1 - x2);
  var _y = Math.abs(y1 - y2);
  return Math.sqrt(_x * _x + _y * _y);
};

const onTouchStart = (e) => {
  var curTouch = e.touches[0];
  uiOptions.startLeft = curTouch.clientX - uiOptions.left;
  uiOptions.startTop = curTouch.clientY - uiOptions.top;

  uiOptions.inDraging = true;
};
const onTouchMove = (e) => {
  var curTouch = e.touches[0];
  var tleft = curTouch.clientX - uiOptions.startLeft;
  var ttop = curTouch.clientY - uiOptions.startTop;

  var distance = getDistance(tleft, ttop, 0, 0);

  if (distance >= props.ballMoveRadius) distance = props.ballMoveRadius;

  var angle = Math.atan2(ttop - 0, tleft - 0);
  uiOptions.left = Math.cos(angle) * distance;
  uiOptions.top = Math.sin(angle) * distance;

  uiOptions.stickHeight = distance;
  uiOptions.angle = angle;
};
const onTouchEnd = (e) => {
    uiOptions.stickHeight = uiOptions.left = uiOptions.top = 0;

    uiOptions.inDraging = false;

  emit("onJoyStickCancel");
};
const loop = () => {
  requestAnimationFrame(loop);

  if (uiOptions.inDraging) {
    emit("onJoyStickUpdate", {
      angle: uiOptions.angle,
      direction: { x: uiOptions.left, y: uiOptions.top },
      power: uiOptions.stickHeight / props.ballMoveRadius,
    });
  }
};
</script>

<style>
.toucharea {
    position: absolute;
    z-index: 4;
    transform: translate(-50%, -50%);
    border-radius: 50%;
}

.ball {
    position: absolute;
    z-index: 3;
    transform: translate(-50%, -50%);
}

.stick {
    position: absolute;
    z-index: 2;
}

.ball.animation {
    transition: left 0.1s ease-out, top 0.1s ease-out;
}

.stick.animation {
    transition: all 0.2s ease-out;
}

.bottom {
    position: absolute;
    z-index: 1;
    transform: translate(-50%, -50%);
}
</style>
